{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Linear Regression\n",
    "\n",
    "Now we will introduce the task of linear regression, the simplest type of machine learning problem. The goal of linear regression is to fit a line to a set of points.  Consider the following dataset:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# x, y\n",
    "data = np.array([\n",
    "    [2.4, 1.7], \n",
    "    [2.8, 1.85], \n",
    "    [3.2, 1.79], \n",
    "    [3.6, 1.95], \n",
    "    [4.0, 2.1], \n",
    "    [4.2, 2.0], \n",
    "    [5.0, 2.7]\n",
    "])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We have a series of {x,y} pairs. We can plot them with a scatterplot."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.PathCollection at 0x109414cf8>"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x109ba40f0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x, y = data[:,0], data[:,1]\n",
    "\n",
    "plt.figure(figsize=(4, 3))\n",
    "plt.scatter(x, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The goal of linear regression is to find a line, $y = mx + b$ which fits the data points as well as possible. \n",
    "\n",
    "What does it mean for it to fit the points \"as well as possible\"? Let's try three random lines and compare them.  We will define the following three functions as candidates:\n",
    "\n",
    "$$f1(x) = 0.92x-1.0$$\n",
    "$$f2(x) = -0.21x+3.4$$\n",
    "$$f3(x) = 0.52x+0.1$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "f1(-1.0) = -1.92\n",
      "f2( 0.0) = 3.40\n",
      "f3( 2.0) = 1.14\n"
     ]
    }
   ],
   "source": [
    "def f1(x):\n",
    "    return 0.92 * x - 1.0\n",
    "\n",
    "def f2(x):\n",
    "    return -0.21 * x + 3.4\n",
    "\n",
    "def f3(x):\n",
    "    return 0.52 * x + 0.1\n",
    "\n",
    "# try some examples\n",
    "print(\"f1(-1.0) = %0.2f\" % f1(-1))\n",
    "print(\"f2( 0.0) = %0.2f\" % f2(0))\n",
    "print(\"f3( 2.0) = %0.2f\" % f3(2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's plot all three of these functions and see how well each of them fit the points in our dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.text.Text at 0x10b128d68>"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x108ec3400>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "min_x, max_x = min(x), max(x)\n",
    "\n",
    "fig = plt.figure(figsize=(10,3))\n",
    "\n",
    "fig.add_subplot(131)\n",
    "plt.scatter(x, y)\n",
    "plt.plot([min_x, max_x], [f1(min_x), f1(max_x)], 'k-')\n",
    "plt.title(\"f1\")\n",
    "\n",
    "fig.add_subplot(132)\n",
    "plt.scatter(x, y)\n",
    "plt.plot([min_x, max_x], [f2(min_x), f2(max_x)], 'k-')\n",
    "plt.title(\"f2\")\n",
    "\n",
    "fig.add_subplot(133)\n",
    "plt.scatter(x, y)\n",
    "plt.plot([min_x, max_x], [f3(min_x), f3(max_x)], 'k-')\n",
    "plt.title(\"f3\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Intuitively, it looks like $f1$ and $f3$ come closest to a good fit, with $f3$ looking somewhat better than $f1$, and $f2$ showing the worst fit. But how do we formally express how good a fit is? We define an \"error\" or \"cost\" function, which expresses the total error between the points predicted by the line, and those of the actual dataset.\n",
    "\n",
    "One very popular measure of this called the \"sum squared error,\" which we will denote as $J$, which is the sum of the square differences between the data points and the line. \n",
    "\n",
    "$$ J = \\sum{(y_i - f(x_i))^2} $$\n",
    "\n",
    "Intuitively, for each pair of points $(x_i, y_i)$, the quantity $y_i - f(x_i)$ is the difference between the actual point $y_i$ and the y-value predicted by the line at $x_i$. Then we square them  (to penalize large distances more) and sum them together. \n",
    "\n",
    "For $f1$, we plot the error bars, $y_i - f_1(x_i)$ with red dashed lines in the next cell."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.text.Text at 0x1093575f8>"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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+Ph4srOz6d27d0R/ycotliCMKcOmTZto06YNEyZM4JlnniErK4vrrrsu3GGFjCUIY3xQVTIyMrjpppvYtWsXn3zyCePHj6devXrhDi2kLEEYU8r+/fvp2LEjTzzxBG3btiU3N5f27duHO6ywsEZKY7ysWLGC1NRUfvzxR8aMGcMf//jHyP0exfvvB/0UliCMAYqKihg5ciTp6elcffXVrFy5klatApo6InwaB38CO7dm9z5PRD4Qka0iskpEEoMRrDHBsH37dm6//XZefvllHn/8cXJyciI/OQB88IFnCaJAahAls3sfFZEY4EsR+VRVs7zK9AIOqOo1ItIZeA3oFIR4jXHV7Nmz6dOnD6rKzJkzSU5ODndIgXvrLc9rp+D9qpVbg1CP8mb3fhDPfJwAc4DfSE14SGyi1rFjx+jVqxedOnXiuuuuY926ddGVHELErdm944GdAKpaBBwCGroZqDFuycnJoWXLlkybNo20tDRWrFjBVVddFe6wIlJACUJVi1W1OXAl0FpErq/MyUSkj4isEZE1e/bsqcwhjKm006dPM27cOG6++WaOHTvG0qVLeeWVV4iJiQl3aBGrQs9vVPUgsAz4balN+UBjABGpA1wI7POxf4aqtlLVVpdccknlIjamEn788Uc6dOjAoEGDaN++Pbm5udx5553hDivildtIKSKXAKdU9aDX7N6vlSr2MdAN+B+gI/C5qpZupzAmLD777DO6du3K4cOHmTRpEn379q0e36OYMyfop3Brdu+pwPsishXP7N6dgxaxMQE6ceIEw4cPZ9y4cVx//fUsXbqU66+v1N1xZGrUKOincGt27+NA9Rlny0S9zZs3k5yczNq1a+nfvz9jxoyhfv364Q7LXdOne167dw/aKSK0D6kxFZOZmUliYiIiQqNGjWjWrBl5eXl89NFHTJw4sfolB/AkiJIkESTW1dpEvczMTPr06UNBQQEA+/bto1atWrzwwgs88MADYY4uulkNwkS9tLS0M8mhxOnTpxlbMuKSqTRLECaqFRcXs2PHDsDz/H2Z17a8vLywxFSdWIIwUWvnzp20a9fO7/YmTZqEMJrqyRKEiUpz586lWbNm5OTk0LdvX2JjY8/aHhsbS3p6epiiC5GFCz1LEFmCMFGloKCAJ554gkcffZRrrrmGtWvX8tZbb5GRkcGbl11GGpCQkEBGRgapqanh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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1093244e0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "min_x, max_x = min(x), max(x)\n",
    "fig = plt.figure(figsize=(4,3))\n",
    "plt.scatter(x, y) # original data points\n",
    "plt.plot([min_x, max_x], [f1(min_x), f1(max_x)], 'k-') # line of f1\n",
    "plt.scatter(x, f1(x), color='black') # points predicted by f1\n",
    "for x_, y_ in zip(x, y):\n",
    "    plt.plot([x_, x_], [y_, f1(x_)], '--', c='red') # error bars\n",
    "plt.title(\"error bars: $y_i-f_1(x_i)$\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Another name for sum squared error is the \"quadratic cost.\" The square root of the sum squared error, $ \\sqrt {\\sum{(y_i -  f(x_i))^2}} $ is the famous \"distance formula\" or \"euclidean distance.\" Dividing by the number of elements $n$, we get the mean squared error, $\\frac{1}{n} \\sum{(y_i -  f(x_i))^2}$, which is the average of the squared differences. All of these cost functions are closely related and are often used interchangeably.\n",
    "\n",
    "For convenience, sum squared error is very often multiplied by $0.5$. The reason for this will be clear later in this notebook. We redefine the sum squared error as:\n",
    "\n",
    "$$ J = \\frac{1}{2} \\sum{(y_i - f(x_i))^2} $$\n",
    "\n",
    "Since the function $f(x_i) = m x_i + b$, we can substitute that into the cost, and get:\n",
    "\n",
    "$$ J = \\frac{1}{2} \\sum{(y_i - (mx_i + b))^2} $$\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "# sum squared error\n",
    "def cost(y_pred, y_actual):\n",
    "    return 0.5 * np.sum((y_actual-y_pred)**2)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "J1=1.18, J2=2.16, J3=0.15\n"
     ]
    }
   ],
   "source": [
    "x, y = data[:,0], data[:,1]\n",
    "\n",
    "J1 = cost(f1(x), y)\n",
    "J2 = cost(f2(x), y)\n",
    "J3 = cost(f3(x), y)\n",
    "\n",
    "print(\"J1=%0.2f, J2=%0.2f, J3=%0.2f\" % (J1, J2, J3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As we expected, the third function has the lowest cost for this dataset, and the second has the highest.\n",
    "\n",
    "What is a good method for finding the optimal $m$ and $b$ to get the lowest error rate? The simplest way would be the brute force method: have the computer make millions of guesses and keep the one that happens to have the lowest error. Computers are pretty fast, so why not? For our simple problem with two parameters, this would work fine. But in real-world problms, we often have dozens, hundreds, or even millions of parameters which have to be optimized at the same time. Making guesses does not scale to a large number of dimensions; no computer is fast enough to try enough guesses to get a good solution in a reasonable amount of time.\n",
    "\n",
    "So we need a more formal method for this. We can get an idea of how we might do this by first observing the loss surface. We'll plot the MSE of every combination of $m$ and $b$ within some range and look at it first. Note: recall that for this toy problem, calculating the cost for all combinations of our two parameters is easy to do because there's a small number of combinations. In problems where we have thousands or more parameters, it will be infeasible to do this practically because there will be too many parameter combinations to try (which is the reason we need a better method than brute force guessing to begin with). For 2 parameters, we observe the loss surface just for demonstration purposes.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.text.Text at 0x1096ce1d0>"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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Icsyfv/732PKlCkxFwo9Hg/uv/9+NDc344UXXkBRURG97XiZ4kGwbt063HbbbZAkCddddx3uu+++oT6lbzJSi3rfJNTX1w/1KYShpaUFS5YsQXt7OziOw4033qj7+X8iIT09HfPnz8f8+fMBALt378ZVV12FmTNnYty4cfjVr36F/fv3o7CwUBfwP3LkSHAcB0VRsGHDBtx77724+eab8fzzz5tW0scTFi5cOBxHKR3XSBHyMEKydT+73Y7HH38cFRUV8Hg8qKyspItPJzry8vKwZs0alJSU0OuIjrxx40Z88skn+N3vfgePx4PS0lJ0dHQgIyMD7733Hk4++eQhO++3334bDzzwAGpqarBp0yZUVVUN2bmkEI6UZDGMIIoiSktL8dFHH6GgoADz5s3DX/7yl6QFli9atAi33HILzjvvvKTs70SAIAj4+uuv8d577+HXv/71oM0UtIqamhrwPI+f/OQneOyxx1KEfOyQkixONNjtdjz99NP47ne/S3W/ZJFxc3Mztm/fjlNPPTUp+ztR4HA4aCb08YBUbvLxjRQhDzMMhu7X19eHSy+9FKtWrTIdIppCCikkBylCTiEqBEHApZdeiquuugqXXHJJ0vYrSRKqqqpQUFCA999/P2n7TSF6SiGx9qVwfCJFyClEhKIouP7661FeXo7bb789qftevXo1ysvL4Xa7k7rfFGI3IKVw/CLVOp1CRHzxxRd47bXX8PHHH2POnDmYM2cO1q1bN+D9tra24oMPPsANN9yQhLNMIYXhg1SFnEJEnH766XHlOljFbbfdhpUrV8Lj8SR93ylExzvvvIOlS5eis7MTF110EebMmUMT3VIYeqQq5GGG5uZmzJgxY6hPIyLef/99jB079rhxHZxouPjii9Ha2opAIID29vYUGR9nSBFyCscUX3zxBd59910UFRVh8eLF+Pjjj3H11VcPeL89PT247LLLMHXqVJSXl+PLL79Mwtke3/jFL36BqVOnYtasWbj44ovR09Mz1KeUwgCRagwZZiATGCorK7Ft2zZMnz4df/7znxMOLBpMbNiwAY899lhSXBbXXHMNzjjjDNxwww0IBoPo7+8f9iOwUlNmvlGw1BiSqpCHIfbu3Yuf/exnqKmpQU5ODp599tmhPqVBRW9vL/7973/T6cZOp3PYkzEAnH/++XQ23/z589Ha2jrEZ5TCQJEi5GGIwsJCfPvb3wYAXH311fj888+H+IzMsWDBgqRUx01NTRgzZgyuvfZazJ07FzfccAO8Xm8SzvCbg5dffhkXXnjhUJ9GCgNEipCHIYypYcdbiliyIYoitm3bhptuugnbt29HZmZmUqalPPnkk5g+fTpmzJiBK6+8En6/PwlnGx+OxZSZFI4fxKshp3Ccg+O4IgBNAL6lKMqXHMe9CKBGUZTHh/TEBhEcx40DsFFRlKLQ5TMA3K0oykUD2GcBgM8BTFMUxcdx3FsA1imK8moSTjlp4DjuxwB+AuAcRVH6h/h0UhggUhXy8MReADdzHFcDYCSA54b4fAYViqIcBtDCcVxZ6KpzAOxJwq7tADI4jrMDcAE4lIR9Jg0cx10A4JcAfpAi4+GBVIWcwrAAx3FzALwIwAmgEcC1iqIcHeA+lwF4GIAPwL8URTmuNAGO4+oBpAE4Erpqo6IoPx3CU0phgEgRcgopmIDjuJEA/gfAFQB6ALwNYI2iKK8P6YmlMKyRkixSSMEc5wJoUhSlU1EUAcD/AvjWEJ9TCsMcKUJOIQVzHAAwn+M4F6faVM4BUDPE55TCMEeKkFNIwQSKolQDWANgG4CdUD8rLwzpSaUw7JHSkFNIIYUUjhOkKuQUUkghheMEKUJOIYUUUjhOkCLkFFJIIYXjBP8f/GF0iIQWXeUAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x109351b70>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from mpl_toolkits.mplot3d import Axes3D\n",
    "\n",
    "fig = plt.figure()\n",
    "ax = fig.gca(projection='3d')\n",
    "\n",
    "# check all combinations of m between [-2, 4] and b between [-6, 8], to precision of 0.1\n",
    "M = np.arange(-2, 4, 0.1)\n",
    "B = np.arange(-6, 8, 0.1)\n",
    "\n",
    "# get MSE at every combination\n",
    "J = np.zeros((len(M), len(B)))\n",
    "for i, m_ in enumerate(M):\n",
    "    for j, b_ in enumerate(B):\n",
    "        J[i][j] = cost(m_*x+b_, y)\n",
    "\n",
    "# plot loss surface\n",
    "B, M = np.meshgrid(B, M)\n",
    "ax.plot_surface(B, M, J, rstride=1, cstride=1, cmap=plt.cm.coolwarm, linewidth=0, antialiased=False)\n",
    "plt.title(\"cost for different m, b\")\n",
    "plt.xlabel(\"b\")\n",
    "plt.ylabel(\"m\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Our loss surface looks a bit like an elongated bowl. Because our goal is to find the parameters $m$ and $b$ which give us the lowest possible error, this translates to finding the point at the bottom of that bowl. By eye, it looks like it's roughly around $m=0, b=2$. \n",
    "\n",
    "### Gradient descent\n",
    "\n",
    "Let's now define a better method for actually finding this point. The method we are going to introduce is called \"gradient descent.\" Note, there is a [much better way to do linear regression](https://machinelearningmastery.com/solve-linear-regression-using-linear-algebra/) than to use gradient descent, but we will use gradient descent anyway, because later on, when we introduce neural networks, we shall see that gradient descent is the best way by which to find the optimal parameters for them. So we introduce gradient descent in the context of a simpler problem first.\n",
    "\n",
    "For a more thorough introduction, gradient descent is discussed in more detail in [this chapter of the book](https://ml4a.github.io/ml4a/how_neural_networks_are_trained/).\n",
    "\n",
    "The basic idea behind gradient descent is as follows. Start with a random guess about the parameters, and then calculate the gradient of the loss function with respect to the parameters. Recall from the previous guide that the gradient of a function is the vector containing each of the partial derivatives of its variables, i.e.\n",
    "\n",
    "$$\n",
    "\\nabla f(X) = \\left[ \\frac{\\partial f}{\\partial x_1}, \\frac{\\partial f}{\\partial x_2}, ..., \\frac{\\partial f}{\\partial x_n}  \\right]\n",
    "$$\n",
    "\n",
    "Our loss function $J$ has two parameters: the slope $m$ and y-intercept $b$. Thus its gradient is:\n",
    "\n",
    "$$\n",
    "\\nabla J = \\left[ \\frac{\\partial J}{\\partial m}, \\frac{\\partial J}{\\partial b} \\right]\n",
    "$$\n",
    "\n",
    "The interpretation of the gradient is that it gives us the slope in every dimension of the loss function at any $m$ and $b$. What gradient descent does is it evaluates the slope of the loss function at the current parameters, and then takes a small step in the exact opposite direction (because the slope is upward). This has the effect of moving $m$ and $b$ to a place where the error is a bit lower than it was before. Repeat this process many times until the loss stops descending (because we have reached the bottom) and you are finished. This is the basic idea.\n",
    "\n",
    "How can we actually calculate the partial derivatives: $\\frac{\\partial J}{\\partial m}$ and $\\frac{\\partial J}{\\partial b}$? We must differentiate $J$ with respect to these two parameters.\n",
    "\n",
    "Recall:\n",
    "\n",
    "$$ J(m,b) = \\frac{1}{2} \\sum{(y_i - (mx_i + b))^2} $$\n",
    "\n",
    "Let's start with $\\frac{\\partial J}{\\partial m}$. We can derive its partial derivative with the following steps:\n",
    "\n",
    "$$ \\frac{\\partial J}{\\partial m} = \\frac{\\partial}{\\partial m} \\left[ \\frac{1}{2} \\sum{(y_i - (mx_i + b))^2} \\right]  $$ \n",
    "\n",
    "We can factor out the $\\frac{1}{2}$ and apply the sum rule of derivatives.\n",
    "\n",
    "$$ \\frac{\\partial J}{\\partial m} = \\frac{1}{2} \\sum{ \\frac{\\partial}{\\partial m} (y_i - (mx_i + b))^2}  $$ \n",
    "\n",
    "Using chain rule, we bring the exponent down, and find that the inner derivative is just $-x_i$.\n",
    "\n",
    "$$ \\frac{\\partial J}{\\partial m} = \\frac{1}{2} \\sum{ -2 x_i \\cdot (y_i - (mx_i + b))}  $$ \n",
    "\n",
    "$$ \\frac{\\partial J}{\\partial m} = -\\sum{x_i \\cdot (y_i - (mx_i + b))} $$\n",
    "\n",
    "For $\\frac{\\partial J}{\\partial b}$, the partial derivative is found:\n",
    "\n",
    "$$ \\frac{\\partial J}{\\partial b} = \\frac{\\partial}{\\partial b} \\left[ \\frac{1}{2} \\sum{(y_i - (mx_i + b))^2} \\right]  $$ \n",
    "\n",
    "Again factor out the $\\frac{1}{2}$ and apply the sum rule of derivatives.\n",
    "\n",
    "$$ \\frac{\\partial J}{\\partial b} = \\frac{1}{2} \\sum{ \\frac{\\partial}{\\partial b} (y_i - (mx_i + b))^2}  $$ \n",
    "\n",
    "Using chain rule, we bring the exponent down, and find that the inner derivative is $-1$.\n",
    "\n",
    "$$ \\frac{\\partial J}{\\partial b} = \\frac{1}{2} \\sum{ -2 \\cdot (y_i - (mx_i + b))}  $$ \n",
    "\n",
    "$$ \\frac{\\partial J}{\\partial b} = -\\sum{(y_i - (mx_i + b))} $$\n",
    "\n",
    "So to summarize, we have found:\n",
    "\n",
    "$$ \\frac{\\partial J}{\\partial m} = - \\sum{x_i \\cdot (y_i - (mx_i + b))} $$\n",
    "$$ \\frac{\\partial J}{\\partial b} = - \\sum{(y_i - (mx_i + b))} $$\n",
    "\n",
    "We can then define the following update rule, where we calculate the gradient and then adjust the parameters $m$ and $b$:\n",
    "\n",
    "$$ m := m - \\alpha \\cdot \\frac{\\partial J}{\\partial m} $$\n",
    "\n",
    "$$ b := b - \\alpha \\cdot \\frac{\\partial J}{\\partial b} $$\n",
    "\n",
    "Where $\\alpha$ is a hyperparameter called the \"learning rate\" that controls the size of the update step. In simple gradient descent, the learning rate must be chosen manually, but as we shall see later, there are more complex variants of gradient descent which automatically pick and adjust the learning rate during training. If we set $\\alpha$ too high, we may overshoot the best trajectory, whereas if we set it too low, learning may take an unacceptably long time. Typical values of this are 0.01, 0.001, 0.0001 and so on.\n",
    "\n",
    "Let's implement this in code:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "initial parameters: m=0.181, b=0.682\n",
      "initial cost = 0.043\n",
      "final parameters: m=0.584, b=0.325\n",
      "final cost = 0.009\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x10971da58>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import random\n",
    "\n",
    "# get our data\n",
    "x, y = data[:,0], data[:,1]\n",
    "\n",
    "# it is a good idea to normalize the data\n",
    "x = x / np.amax(x, axis=0)\n",
    "y = y / np.amax(y, axis=0)\n",
    "\n",
    "# choose a random initial m, b\n",
    "m, b = random.random(), random.random()#0.8, -0.5\n",
    "\n",
    "def F(x, m, b):\n",
    "    return m * x + b\n",
    "\n",
    "# what is our error?\n",
    "y_pred = F(x, m, b)\n",
    "init_cost = cost(y_pred, y)\n",
    "\n",
    "print(\"initial parameters: m=%0.3f, b=%0.3f\"%(m, b))\n",
    "print(\"initial cost = %0.3f\" % init_cost)\n",
    "\n",
    "# implement partial derivatives of our parameters\n",
    "def dJdm(x, y, m, b):\n",
    "    return -np.dot(x, y - F(x, m, b))\n",
    "\n",
    "def dJdb(x, y, m, b):\n",
    "    return -np.sum(y - F(x, m, b))\n",
    "\n",
    "# choose the alpha parameter and number of iterations\n",
    "alpha = 0.01\n",
    "n_iters = 2000\n",
    "\n",
    "# keep track of error\n",
    "errors = []\n",
    "for i in range(n_iters):\n",
    "    m = m - alpha * dJdm(x, y, m, b)\n",
    "    b = b - alpha * dJdb(x, y, m, b)\n",
    "    y_pred = F(x, m, b)\n",
    "    j = cost(y_pred, y)\n",
    "    errors.append(j)\n",
    "    \n",
    "# plot it\n",
    "plt.figure(figsize=(16, 3))\n",
    "plt.plot(range(n_iters), errors, linewidth=2)\n",
    "plt.title(\"Cost by iteration\")\n",
    "plt.ylabel(\"Cost\")\n",
    "plt.xlabel(\"iterations\")\n",
    "\n",
    "# what is our final error rate\n",
    "y_pred = F(x, m, b)\n",
    "final_cost = cost(y_pred, y)\n",
    "\n",
    "print(\"final parameters: m=%0.3f, b=%0.3f\"%(m, b))\n",
    "print(\"final cost = %0.3f\" % final_cost)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can plot the line of best fit:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.text.Text at 0x1093cee48>"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x10c40d198>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "min_x, max_x = min(x), max(x)\n",
    "\n",
    "fig = plt.figure(figsize=(3,3))\n",
    "plt.scatter(x, y)\n",
    "plt.plot([min_x, max_x], [m * min_x + b, m * max_x + b], 'k-')\n",
    "plt.title(\"line of best fit\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The procedure that we just demonstrated is called \"gradient descent.\" It's not actually necessary to do linear regression, because linear regression can be solved analytically. However, in the next guide we will introduce neural networks, which can not be optimized analytically, and thus will require gradient descent to train."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
